////////////////////////////////////////////////
// MACHINE GENERATED, PLEASE DONOT MODIFY!    //
////////////////////////////////////////////////

#pragma once

#include "../../plugin/base/module_frame.hh"
#include "../../plugin/base/framework.hh"
#include "../../plugin/protocol/protocol_header.hh"
#include "../../plugin/base/rpc_base.hh"
#include "../../plugin/base/entity.hh"
#include "../../corelib/object_pool.hpp"
#include "rpc_generated.hh"

enum class ProxyType {
    PROXYTYPE_PATH = 1,
    PROXYTYPE_SITE,
    PROXYTYPE_ENTITY,
};

RPCSkeleton* skeleton_ = nullptr;

void RPCSkeleton::install() {
    if (!skeleton_) {
        skeleton_ = new RPCSkeleton();
    }
}

void RPCSkeleton::uninstall() {
    delete skeleton_;
    skeleton_ = nullptr;
}

RPCSkeleton::RPCSkeleton() {
    RPCRef.registerSkeleton(this);
}

RPCSkeleton::~RPCSkeleton() {
    RPCRef.registerSkeleton(nullptr);
}

template <typename MSG, typename METHOD>
static bool callMethod(ProxyType type, std::uint64_t id, std::uint64_t RPCID, const MSG& msg, METHOD method, RPCTimeoutCB toCB, std::time_t timeout) {
    auto call = kratos::corelib::allocate<RPCCall<METHOD>>();
    if (!call) {
        return false;
    }
    call->ackMethod = method;
    if (type == ProxyType::PROXYTYPE_PATH) {
        if (!RPCRef.RPCCallByPath(static_cast<PathID>(id), RPCID, msg, call, toCB, timeout)) {
            kratos::corelib::dispose(call);
            return false;
        }
    } else if (type == ProxyType::PROXYTYPE_SITE) {
        if (!RPCRef.RPCCallBySite(kratos::grid::SiteID(id), RPCID, msg, call, toCB, timeout)) {
            kratos::corelib::dispose(call);
            return false;
        }
    } else if (type == ProxyType::PROXYTYPE_ENTITY) {
        if (!RPCRef.RPCCallByEntity(id, RPCID, msg, call, toCB, timeout)) {
            kratos::corelib::dispose(call);
            return false;
        }
    } else {
        kratos::corelib::dispose(call);
        return false;
    }
    return true;
}

ISample* Sample_ = nullptr;
ISample1* Sample1_ = nullptr;

static void ON_SAMPLE_ECHO(const DummyReq& req,DummyAck& ack, std::uint64_t entityID = 0);
static void ON_PATH_SAMPLE_ECHO(PathID pathID, std::uint64_t UUID, std::uint64_t RPCID, const char* data, std::size_t size, ProxyType proxyType = ProxyType::PROXYTYPE_PATH, PathID fromPathID = 0, std::uint64_t entityID = 0);
static void ON_SITE_SAMPLE_ECHO(const kratos::grid::SiteID& siteID, std::uint64_t UUID, std::uint64_t RPCID, const char* data, std::size_t size);
static void ON_SAMPLE_ECHO_ACK(RPCCallBase* callBase, const char* data, std::size_t size);

static void ON_SAMPLE_ECHO1(const DummyReq& req,DummyAck& ack, std::uint64_t entityID = 0);
static void ON_PATH_SAMPLE_ECHO1(PathID pathID, std::uint64_t UUID, std::uint64_t RPCID, const char* data, std::size_t size, ProxyType proxyType = ProxyType::PROXYTYPE_PATH, PathID fromPathID = 0, std::uint64_t entityID = 0);
static void ON_SITE_SAMPLE_ECHO1(const kratos::grid::SiteID& siteID, std::uint64_t UUID, std::uint64_t RPCID, const char* data, std::size_t size);
static void ON_SAMPLE_ECHO1_ACK(RPCCallBase* callBase, const char* data, std::size_t size);


static void ON_SAMPLE1_ECHO(const DummyReq& req,DummyAck& ack, std::uint64_t entityID = 0);
static void ON_PATH_SAMPLE1_ECHO(PathID pathID, std::uint64_t UUID, std::uint64_t RPCID, const char* data, std::size_t size, ProxyType proxyType = ProxyType::PROXYTYPE_PATH, PathID fromPathID = 0, std::uint64_t entityID = 0);
static void ON_SITE_SAMPLE1_ECHO(const kratos::grid::SiteID& siteID, std::uint64_t UUID, std::uint64_t RPCID, const char* data, std::size_t size);
static void ON_SAMPLE1_ECHO_ACK(RPCCallBase* callBase, const char* data, std::size_t size);

static void ON_SAMPLE1_ECHO1(const DummyReq& req,DummyAck& ack, std::uint64_t entityID = 0);
static void ON_PATH_SAMPLE1_ECHO1(PathID pathID, std::uint64_t UUID, std::uint64_t RPCID, const char* data, std::size_t size, ProxyType proxyType = ProxyType::PROXYTYPE_PATH, PathID fromPathID = 0, std::uint64_t entityID = 0);
static void ON_SITE_SAMPLE1_ECHO1(const kratos::grid::SiteID& siteID, std::uint64_t UUID, std::uint64_t RPCID, const char* data, std::size_t size);
static void ON_SAMPLE1_ECHO1_ACK(RPCCallBase* callBase, const char* data, std::size_t size);


void RPCSkeleton::registerImpl(ISample* impl) {
	Sample_ = impl;
}

void RPCSkeleton::registerImpl(ISample1* impl) {
	Sample1_ = impl;
}


class RPCInterface_Sample_proxy_impl : public SampleProxy {
	ProxyType proxyType_;
	std::uint64_t id_;

public:
	RPCInterface_Sample_proxy_impl(ProxyType type, std::uint64_t id) {
		proxyType_ = type;
		id_ = id;
	}
	virtual bool echo(const DummyReq& req, SampleEchoFunction method = nullptr, RPCTimeoutCB toCB = nullptr, std::time_t timeout = 2000) override {
		return callMethod<DummyReq,SampleEchoFunction>(proxyType_, id_, RPC_ID_SAMPLE_ECHO,req, method, toCB, timeout);
	}
	virtual bool echo1(const DummyReq& req, SampleEcho1Function method = nullptr, RPCTimeoutCB toCB = nullptr, std::time_t timeout = 2000) override {
		return callMethod<DummyReq,SampleEcho1Function>(proxyType_, id_, RPC_ID_SAMPLE_ECHO1,req, method, toCB, timeout);
	}
};

class RPCInterface_Sample1_proxy_impl : public Sample1Proxy {
	ProxyType proxyType_;
	std::uint64_t id_;

public:
	RPCInterface_Sample1_proxy_impl(ProxyType type, std::uint64_t id) {
		proxyType_ = type;
		id_ = id;
	}
	virtual bool echo(const DummyReq& req, Sample1EchoFunction method = nullptr, RPCTimeoutCB toCB = nullptr, std::time_t timeout = 2000) override {
		return callMethod<DummyReq,Sample1EchoFunction>(proxyType_, id_, RPC_ID_SAMPLE1_ECHO,req, method, toCB, timeout);
	}
	virtual bool echo1(const DummyReq& req, Sample1Echo1Function method = nullptr, RPCTimeoutCB toCB = nullptr, std::time_t timeout = 2000) override {
		return callMethod<DummyReq,Sample1Echo1Function>(proxyType_, id_, RPC_ID_SAMPLE1_ECHO1,req, method, toCB, timeout);
	}
};

std::shared_ptr<SampleProxy> RPCSkeleton::Path::getSample(PathID pathID) {
	return std::shared_ptr<SampleProxy>(new RPCInterface_Sample_proxy_impl(ProxyType::PROXYTYPE_PATH,static_cast<std::uint64_t>(pathID)));
}

std::shared_ptr<SampleProxy> RPCSkeleton::Site::getSample(const kratos::grid::SiteID& siteID) {
	return std::shared_ptr<SampleProxy>(new RPCInterface_Sample_proxy_impl(ProxyType::PROXYTYPE_SITE,siteID.u64()));
}

std::shared_ptr<SampleProxy> RPCSkeleton::Entity::getSample(std::uint64_t entityID) {
	return std::shared_ptr<SampleProxy>(new RPCInterface_Sample_proxy_impl(ProxyType::PROXYTYPE_ENTITY,entityID));
}

std::shared_ptr<Sample1Proxy> RPCSkeleton::Path::getSample1(PathID pathID) {
	return std::shared_ptr<Sample1Proxy>(new RPCInterface_Sample1_proxy_impl(ProxyType::PROXYTYPE_PATH,static_cast<std::uint64_t>(pathID)));
}

std::shared_ptr<Sample1Proxy> RPCSkeleton::Site::getSample1(const kratos::grid::SiteID& siteID) {
	return std::shared_ptr<Sample1Proxy>(new RPCInterface_Sample1_proxy_impl(ProxyType::PROXYTYPE_SITE,siteID.u64()));
}

std::shared_ptr<Sample1Proxy> RPCSkeleton::Entity::getSample1(std::uint64_t entityID) {
	return std::shared_ptr<Sample1Proxy>(new RPCInterface_Sample1_proxy_impl(ProxyType::PROXYTYPE_ENTITY,entityID));
}

void RPCSkeleton::dispose(std::uint64_t RPCID, RPCCallBase * callBase) {
	switch (RPCID) {
		case RPC_ID_SAMPLE_ECHO:
			kratos::corelib::dispose(dynamic_cast<RPCCall<SampleEchoFunction>*>(callBase));
			return;
		case RPC_ID_SAMPLE_ECHO1:
			kratos::corelib::dispose(dynamic_cast<RPCCall<SampleEcho1Function>*>(callBase));
			return;
		case RPC_ID_SAMPLE1_ECHO:
			kratos::corelib::dispose(dynamic_cast<RPCCall<Sample1EchoFunction>*>(callBase));
			return;
		case RPC_ID_SAMPLE1_ECHO1:
			kratos::corelib::dispose(dynamic_cast<RPCCall<Sample1Echo1Function>*>(callBase));
			return;
		default:
			return;
	}
}
void RPCSkeleton::onPathReq(PathID pathID, std::uint64_t RPCID, std::uint64_t UUID, const char * data, std::size_t size) {
	switch (RPCID) {
		case RPC_ID_SAMPLE_ECHO:
			ON_PATH_SAMPLE_ECHO(pathID, UUID, RPCID, data, size);
			break;
		case RPC_ID_SAMPLE_ECHO1:
			ON_PATH_SAMPLE_ECHO1(pathID, UUID, RPCID, data, size);
			break;
		case RPC_ID_SAMPLE1_ECHO:
			ON_PATH_SAMPLE1_ECHO(pathID, UUID, RPCID, data, size);
			break;
		case RPC_ID_SAMPLE1_ECHO1:
			ON_PATH_SAMPLE1_ECHO1(pathID, UUID, RPCID, data, size);
			break;
		default:
			return;
	}
}
void RPCSkeleton::onPathAck(std::uint64_t RPCID, RPCCallBase * callBase, const char * data, std::size_t size) {
	switch (RPCID) {
		case RPC_ID_SAMPLE_ECHO:
			ON_SAMPLE_ECHO_ACK(callBase, data, size);
			break;
		case RPC_ID_SAMPLE_ECHO1:
			ON_SAMPLE_ECHO1_ACK(callBase, data, size);
			break;
		case RPC_ID_SAMPLE1_ECHO:
			ON_SAMPLE1_ECHO_ACK(callBase, data, size);
			break;
		case RPC_ID_SAMPLE1_ECHO1:
			ON_SAMPLE1_ECHO1_ACK(callBase, data, size);
			break;
		default:
			return;
	}
}
void RPCSkeleton::onSiteReq(const kratos::grid::SiteID & siteID, std::uint64_t RPCID, std::uint64_t UUID, const char * data, std::size_t size) {
	switch (RPCID) {
		case RPC_ID_SAMPLE_ECHO:
			ON_SITE_SAMPLE_ECHO(siteID, UUID, RPCID, data, size);
			break;
		case RPC_ID_SAMPLE_ECHO1:
			ON_SITE_SAMPLE_ECHO1(siteID, UUID, RPCID, data, size);
			break;
		case RPC_ID_SAMPLE1_ECHO:
			ON_SITE_SAMPLE1_ECHO(siteID, UUID, RPCID, data, size);
			break;
		case RPC_ID_SAMPLE1_ECHO1:
			ON_SITE_SAMPLE1_ECHO1(siteID, UUID, RPCID, data, size);
			break;
		default:
			return;
	}
}
void RPCSkeleton::onSiteAck(std::uint64_t RPCID, RPCCallBase * callBase, const char * data, std::size_t size) {
	switch (RPCID) {
		case RPC_ID_SAMPLE_ECHO:
			ON_SAMPLE_ECHO_ACK(callBase, data, size);
			break;
		case RPC_ID_SAMPLE_ECHO1:
			ON_SAMPLE_ECHO1_ACK(callBase, data, size);
			break;
		case RPC_ID_SAMPLE1_ECHO:
			ON_SAMPLE1_ECHO_ACK(callBase, data, size);
			break;
		case RPC_ID_SAMPLE1_ECHO1:
			ON_SAMPLE1_ECHO1_ACK(callBase, data, size);
			break;
		default:
			return;
	}
}
void RPCSkeleton::onEntityReq(PathID pathID, PathID fromPathID, std::uint64_t entityID, std::uint64_t RPCID, std::uint64_t UUID, const char * data, std::size_t size) {
	switch (RPCID) {
		case RPC_ID_SAMPLE_ECHO:
			ON_PATH_SAMPLE_ECHO(pathID, UUID, RPCID, data, size, ProxyType::PROXYTYPE_ENTITY, fromPathID, entityID);
			break;
		case RPC_ID_SAMPLE_ECHO1:
			ON_PATH_SAMPLE_ECHO1(pathID, UUID, RPCID, data, size, ProxyType::PROXYTYPE_ENTITY, fromPathID, entityID);
			break;
		case RPC_ID_SAMPLE1_ECHO:
			ON_PATH_SAMPLE1_ECHO(pathID, UUID, RPCID, data, size, ProxyType::PROXYTYPE_ENTITY, fromPathID, entityID);
			break;
		case RPC_ID_SAMPLE1_ECHO1:
			ON_PATH_SAMPLE1_ECHO1(pathID, UUID, RPCID, data, size, ProxyType::PROXYTYPE_ENTITY, fromPathID, entityID);
			break;
		default:
			return;
	}
}

void RPCSkeleton::onEntityAck(std::uint64_t RPCID, RPCCallBase * callBase, const char * data, std::size_t size) {
	onPathAck(RPCID, callBase, data, size);
}

void ON_PATH_SAMPLE_ECHO(PathID pathID, std::uint64_t UUID, std::uint64_t RPCID, const char * data, std::size_t size, ProxyType proxyType, PathID fromPathID, std::uint64_t entityID) {
	DummyReq req;
	req.ParseFromArray(data, size);
	DummyAck ack;
	ON_SAMPLE_ECHO(req, ack, entityID);
	if(proxyType==ProxyType::PROXYTYPE_PATH) {
		sendPathAck(pathID, UUID, RPCID, ack);
	} else {
		sendEntityAck(pathID, fromPathID, UUID, RPCID, ack);
	}
}


void ON_PATH_SAMPLE_ECHO1(PathID pathID, std::uint64_t UUID, std::uint64_t RPCID, const char * data, std::size_t size, ProxyType proxyType, PathID fromPathID, std::uint64_t entityID) {
	DummyReq req;
	req.ParseFromArray(data, size);
	DummyAck ack;
	ON_SAMPLE_ECHO1(req, ack, entityID);
	if(proxyType==ProxyType::PROXYTYPE_PATH) {
		sendPathAck(pathID, UUID, RPCID, ack);
	} else {
		sendEntityAck(pathID, fromPathID, UUID, RPCID, ack);
	}
}


void ON_PATH_SAMPLE1_ECHO(PathID pathID, std::uint64_t UUID, std::uint64_t RPCID, const char * data, std::size_t size, ProxyType proxyType, PathID fromPathID, std::uint64_t entityID) {
	DummyReq req;
	req.ParseFromArray(data, size);
	DummyAck ack;
	ON_SAMPLE1_ECHO(req, ack, entityID);
	if(proxyType==ProxyType::PROXYTYPE_PATH) {
		sendPathAck(pathID, UUID, RPCID, ack);
	} else {
		sendEntityAck(pathID, fromPathID, UUID, RPCID, ack);
	}
}


void ON_PATH_SAMPLE1_ECHO1(PathID pathID, std::uint64_t UUID, std::uint64_t RPCID, const char * data, std::size_t size, ProxyType proxyType, PathID fromPathID, std::uint64_t entityID) {
	DummyReq req;
	req.ParseFromArray(data, size);
	DummyAck ack;
	ON_SAMPLE1_ECHO1(req, ack, entityID);
	if(proxyType==ProxyType::PROXYTYPE_PATH) {
		sendPathAck(pathID, UUID, RPCID, ack);
	} else {
		sendEntityAck(pathID, fromPathID, UUID, RPCID, ack);
	}
}


void ON_SAMPLE_ECHO(const DummyReq& req, DummyAck& ack, std::uint64_t entityID) {
	if(entityID) {
		auto entity = EntityManagerRef.getEntityByType<ISample>(entityID);
		if(entity) {
			entity->echo(req, ack);
		} else {
			if (Sample_) {
				Sample_->echo(req, ack);
			} else {
				errorlog << "Calling umimplemented interface method RPCInterface_Sample::echo" << endlog;
			}
		}
		return;
	}
	if (Sample_) {
		Sample_->echo(req, ack);
	} else {
		errorlog << "Calling umimplemented interface method RPCInterface_Sample::echo" << endlog;
	}
}

void ON_SAMPLE_ECHO1(const DummyReq& req, DummyAck& ack, std::uint64_t entityID) {
	if(entityID) {
		auto entity = EntityManagerRef.getEntityByType<ISample>(entityID);
		if(entity) {
			entity->echo1(req, ack);
		} else {
			if (Sample_) {
				Sample_->echo1(req, ack);
			} else {
				errorlog << "Calling umimplemented interface method RPCInterface_Sample::echo1" << endlog;
			}
		}
		return;
	}
	if (Sample_) {
		Sample_->echo1(req, ack);
	} else {
		errorlog << "Calling umimplemented interface method RPCInterface_Sample::echo1" << endlog;
	}
}

void ON_SAMPLE1_ECHO(const DummyReq& req, DummyAck& ack, std::uint64_t entityID) {
	if(entityID) {
		auto entity = EntityManagerRef.getEntityByType<ISample1>(entityID);
		if(entity) {
			entity->echo(req, ack);
		} else {
			if (Sample1_) {
				Sample1_->echo(req, ack);
			} else {
				errorlog << "Calling umimplemented interface method RPCInterface_Sample1::echo" << endlog;
			}
		}
		return;
	}
	if (Sample1_) {
		Sample1_->echo(req, ack);
	} else {
		errorlog << "Calling umimplemented interface method RPCInterface_Sample1::echo" << endlog;
	}
}

void ON_SAMPLE1_ECHO1(const DummyReq& req, DummyAck& ack, std::uint64_t entityID) {
	if(entityID) {
		auto entity = EntityManagerRef.getEntityByType<ISample1>(entityID);
		if(entity) {
			entity->echo1(req, ack);
		} else {
			if (Sample1_) {
				Sample1_->echo1(req, ack);
			} else {
				errorlog << "Calling umimplemented interface method RPCInterface_Sample1::echo1" << endlog;
			}
		}
		return;
	}
	if (Sample1_) {
		Sample1_->echo1(req, ack);
	} else {
		errorlog << "Calling umimplemented interface method RPCInterface_Sample1::echo1" << endlog;
	}
}

void ON_SITE_SAMPLE_ECHO(const kratos::grid::SiteID & siteID, std::uint64_t UUID, std::uint64_t RPCID, const char * data, std::size_t size) {
	DummyReq req;
	req.ParseFromArray(data, size);
	DummyAck ack;
	ON_SAMPLE_ECHO(req, ack);
	sendSiteAck(siteID, UUID, RPCID, ack);
}

void ON_SITE_SAMPLE_ECHO1(const kratos::grid::SiteID & siteID, std::uint64_t UUID, std::uint64_t RPCID, const char * data, std::size_t size) {
	DummyReq req;
	req.ParseFromArray(data, size);
	DummyAck ack;
	ON_SAMPLE_ECHO1(req, ack);
	sendSiteAck(siteID, UUID, RPCID, ack);
}

void ON_SITE_SAMPLE1_ECHO(const kratos::grid::SiteID & siteID, std::uint64_t UUID, std::uint64_t RPCID, const char * data, std::size_t size) {
	DummyReq req;
	req.ParseFromArray(data, size);
	DummyAck ack;
	ON_SAMPLE1_ECHO(req, ack);
	sendSiteAck(siteID, UUID, RPCID, ack);
}

void ON_SITE_SAMPLE1_ECHO1(const kratos::grid::SiteID & siteID, std::uint64_t UUID, std::uint64_t RPCID, const char * data, std::size_t size) {
	DummyReq req;
	req.ParseFromArray(data, size);
	DummyAck ack;
	ON_SAMPLE1_ECHO1(req, ack);
	sendSiteAck(siteID, UUID, RPCID, ack);
}

void ON_SAMPLE_ECHO_ACK(RPCCallBase * callBase, const char * data, std::size_t size) {
	auto call = dynamic_cast<RPCCall<SampleEchoFunction>*>(callBase);
	if (!call->ackMethod) {
		return;
	}
	DummyAck ack;
	ack.ParseFromArray(data, size);
	try {
		call->ackMethod(ack);
	} catch (std::exception& e) {
		errorlog << "Exception:" << e.what() << ", when processing result of RPCID:" << callBase->RPCID << endlog;
	}
}

void ON_SAMPLE_ECHO1_ACK(RPCCallBase * callBase, const char * data, std::size_t size) {
	auto call = dynamic_cast<RPCCall<SampleEcho1Function>*>(callBase);
	if (!call->ackMethod) {
		return;
	}
	DummyAck ack;
	ack.ParseFromArray(data, size);
	try {
		call->ackMethod(ack);
	} catch (std::exception& e) {
		errorlog << "Exception:" << e.what() << ", when processing result of RPCID:" << callBase->RPCID << endlog;
	}
}

void ON_SAMPLE1_ECHO_ACK(RPCCallBase * callBase, const char * data, std::size_t size) {
	auto call = dynamic_cast<RPCCall<Sample1EchoFunction>*>(callBase);
	if (!call->ackMethod) {
		return;
	}
	DummyAck ack;
	ack.ParseFromArray(data, size);
	try {
		call->ackMethod(ack);
	} catch (std::exception& e) {
		errorlog << "Exception:" << e.what() << ", when processing result of RPCID:" << callBase->RPCID << endlog;
	}
}

void ON_SAMPLE1_ECHO1_ACK(RPCCallBase * callBase, const char * data, std::size_t size) {
	auto call = dynamic_cast<RPCCall<Sample1Echo1Function>*>(callBase);
	if (!call->ackMethod) {
		return;
	}
	DummyAck ack;
	ack.ParseFromArray(data, size);
	try {
		call->ackMethod(ack);
	} catch (std::exception& e) {
		errorlog << "Exception:" << e.what() << ", when processing result of RPCID:" << callBase->RPCID << endlog;
	}
}

